﻿/*******************************************************************************
* file  : rsa demo
* creat : apleilx
* data  : 2017/03/02
* @brief  	rsa 是一种非对称加密算法，加密解密KEY不同
*			此算法的应用传递过程：
*			A：生成密匙对，一个为公匙（用于传递），一个为私匙（自己持有）
*			B: 向A请求公匙
*			A：发送公匙给B
*			B: 用公匙加密数据发送给A
*			A：用私匙解密数据。用私匙加密数据发送给B
*			B: 用公匙解密数据
*******************************************************************************/
#include "common.h"
#include "crc_ext.h"
#include "mbedtls/rsa.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "bsp_api.h"
#include "stdio_cfg.h"
#include "os_obj.h"
#include "sys_task.h"
#include "mbedtls/platform.h"
#include "mbedtls/bignum.h"

/*
********************************************************************************
*                              MICRO
*******************************************************************************/
#define MBEDTLS_AES_C
#define MBEDTLS_SHA256_C
#define MBEDTLS_ENTROPY_C
#define MBEDTLS_CTR_DRBG_C
#define MBEDTLS_BIGNUM_C
#define MBEDTLS_GENPRIME
#define MBEDTLS_MD_C
#define MBEDTLS_OID_C      //开启OID数据结构模块
#define MBEDTLS_RSA_C      //开启RSA算法
#define MBEDTLS_PKCS1_V21  //开启PKCS#1 v2.1方案
#define MBEDTLS_AES_ROM_TABLES

/*
********************************************************************************
*                              function
*******************************************************************************/
extern void * rsa_src, *rsa_enc, *rsa_dec;
#define DEV_RANDOM_THRESHOLD        32
int rsa_random_entropy_poll( void *, unsigned char *, size_t, size_t *);
static const char pers[] = "simple_rsa";

/*
********************************************************************************
*                              assert
*******************************************************************************/
#define assert_exit(cond, ret) \
    do { if (!(cond)) { \
        printf("  !. assert: failed [line: %d, error: -0x%04X]\n", __LINE__, -ret); \
        goto cleanup; \
    } } while (0)

/*
********************************************************************************
*                              display
*******************************************************************************/
void dump_buf(char *info, uint8_t *buf, uint32_t len)
{
    mbedtls_printf("%s", info);
    for (int i = 0; i < len; i++) {
        mbedtls_printf("%s%02X%s", i % 16 == 0 ? "\n     ":" ", 
                        buf[i], i == len - 1 ? "\n":"");
    }
}

void dump_rsa_key(mbedtls_rsa_context *ctx);

/*
********************************************************************************
*                              main
*******************************************************************************/
int rsa_gen_and_crypto(void)
{
    int ret;
    size_t olen = 0;

    mbedtls_rsa_context *ctx;    //RSA密钥结构体
    mbedtls_entropy_context *entropy;
    mbedtls_ctr_drbg_context *ctr_drbg;
	
	ctx = malloc(sizeof(mbedtls_rsa_context));
	entropy = malloc(sizeof(mbedtls_entropy_context));
	ctr_drbg = malloc(sizeof(mbedtls_ctr_drbg_context));
	
	copy_str("Hello, World!", rsa_src, 200);
	
    mbedtls_entropy_init(entropy);		//初始化熵结构体
    mbedtls_ctr_drbg_init(ctr_drbg);	//初始化随机数结构体
	
    //rsa结构体初始化
    mbedtls_rsa_init(ctx);  
    						 
	// 填充方案OAEP //SHA256做散列算法
    mbedtls_rsa_set_padding(ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
	
	// 随机数生成器
	ret = mbedtls_entropy_add_source( 
		entropy, 
		rsa_random_entropy_poll,
		NULL, 
		DEV_RANDOM_THRESHOLD,
		MBEDTLS_ENTROPY_SOURCE_STRONG );
	
	assert_exit(ret == 0, ret);
	
    ret = mbedtls_ctr_drbg_seed(
		ctr_drbg, 
		mbedtls_entropy_func, 
		entropy, 
        (const uint8_t *) pers, 
		strlen(pers));				//根据个性化字符串更新种子
	
    assert_exit(ret == 0, ret);
    mbedtls_printf("\n  . setup rng ... ok\n");
    mbedtls_printf("\n  ! RSA Generating large primes may take minutes! \n");
	
	// 生成RSA密钥
    ret = mbedtls_rsa_gen_key(
		ctx, 
		mbedtls_ctr_drbg_random,	//随机数生成接口
		ctr_drbg,					//随机数结构体
		1024,						//模数位长度,即密匙长度、加密数据块长度
		65537);						//公开指数0x01001
    assert_exit(ret == 0, ret);                                    
    mbedtls_printf("\n  1. RSA generate key ... ok\n");
    dump_rsa_key(ctx);  
	
    // RSA 公匙 加密
    ret = mbedtls_rsa_pkcs1_encrypt(
		ctx, 
		mbedtls_ctr_drbg_random,	//随机数生成接口
		ctr_drbg,          			//随机数结构体
		40,							//消息长度
		rsa_src,					//输入消息指针
		rsa_enc);					//输出密文指针
    assert_exit(ret == 0, ret);                              
    dump_buf("\n  2. RSA public key encryption ... ok", rsa_enc, 128);
	
	// RSA 私匙 解密
    ret = mbedtls_rsa_pkcs1_decrypt(
		ctx, 
		mbedtls_ctr_drbg_random,	//随机数生成接口
		ctr_drbg,					//随机数结构体
		&olen,						//输出长度
		rsa_enc,					//输入密文指针
		rsa_dec,					//输出明文指针
		2048);						//最大输出明文数组长度
    assert_exit(ret == 0, ret);                              
    
    mbedtls_printf("\n  3. RSA privite key decryption ... ok! len = %d\n", olen);

	// 结果验证
    ret = memcmp(rsa_src, rsa_dec, olen);
    assert_exit(ret == 0, ret);      

	dbg_print("\tsrc : %s \n" ,rsa_src);
	dbg_print("\tdec : %s \n" ,rsa_dec);
	
	// END
cleanup:
    mbedtls_ctr_drbg_free(ctr_drbg);	//释放随机数结构体
    mbedtls_entropy_free(entropy);		//释放熵结构体
    mbedtls_rsa_free(ctx);				//释放rsa结构体

	// 释放内存
	free(ctx);
	free(entropy);
	free(ctr_drbg);
	
    return ret;
}
